﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;

namespace Maydew.Windows.Forms.Controls.FlexiCell
{
    /// <summary>
    /// 为 Cell 类提供集合管理。
    /// </summary>
    public class CellCollection : System.Collections.CollectionBase
    {
        #region " 事件 "
        /// <summary>
        /// 当集合改变后发生。
        /// </summary>
        public event CollectionChangeEventHandler Changed;
        #endregion

        #region " 私有变量 "
        /// <summary>
        /// 获取绘图面板。
        /// </summary>
        private Control _canvas;
        /// <summary>
        /// 单元格行集合。
        /// </summary>
        private Dictionary<int, List<Cell>> _rowCells;
        /// <summary>
        /// 单元格列集合。
        /// </summary>
        private Dictionary<string, List<Cell>> _columnCells;
        #endregion

        #region " 构造函数 "
        /// <summary>
        /// 初始化 CellCollection 类的新实例。
        /// </summary>
        public CellCollection()
            : this(null)
        {

        }
        /// <summary>
        /// 初始化 CellCollection 类的新实例。
        /// </summary>
        /// <param name="canvas">绘图面板。</param>
        public CellCollection(Control canvas)
        {
            _canvas = canvas;
            _rowCells = new Dictionary<int, List<Cell>>();
            _columnCells = new Dictionary<string, List<Cell>>();
        }
        #endregion

        #region " 索引器 "
        /// <summary>
        /// 获取或设置单元格。
        /// </summary>
        /// <param name="index">单元格索引。</param>
        /// <returns>返回 Cell 对象。</returns>
        public Cell this[int index]
        {
            get
            {
                return (Cell)List[index];
            }
            set
            {
                List[index] = value;
            }
        }
        /// <summary>
        /// 获取单元格。
        /// </summary>
        /// <param name="rowIndex">行号。</param>
        /// <param name="columnName">列名。</param>
        /// <returns>返回 Cell 对象。</returns>
        public Cell this[int rowIndex, string columnName]
        {
            get
            {
                return GetCell(rowIndex, columnName);
            }
        }
        #endregion

        #region " 属性 "
        /// <summary>
        /// 获取绘图面板。
        /// </summary>
        public Control Canvas
        {
            get
            {
                return _canvas;
            }
        }
        #endregion

        #region " 方法 "
        /// <summary>
        /// 添加单元格。
        /// </summary>
        /// <param name="cell">单元格。</param>
        /// <returns>返回插入后的索引。</returns>
        public int Add(Cell cell)
        {
            return List.Add(cell);
        }
        /// <summary>
        /// 插入单元格。
        /// </summary>
        /// <param name="index">要插入的索引。</param>
        /// <param name="cell">单元格。</param>
        public void Insert(int index, Cell cell)
        {
            List.Insert(index, cell);
        }
        /// <summary>
        /// 移除单元格。
        /// </summary>
        /// <param name="cell">单元格。</param>
        public void Remove(Cell cell)
        {
            List.Remove(cell);
        }
        /// <summary>
        /// 获取单元格的索引。
        /// </summary>
        /// <param name="cell">单元格。</param>
        /// <returns>成功返回单元格索引，否则，返回 -1。</returns>
        public int IndexOf(Cell cell)
        {
            return List.IndexOf(cell);
        }
        /// <summary>
        /// 获取单元格是否包含在集合中。
        /// </summary>
        /// <param name="cell">单元格。</param>
        /// <returns>成功返回 True，否则，返回 False。</returns>
        public bool Contains(Cell cell)
        {
            return List.Contains(cell);
        }
        /// <summary>
        /// 获取整行单元格集合。
        /// </summary>
        /// <param name="rowIndex">行号。</param>
        /// <returns>返回单元格集合。</returns>
        public List<Cell> GetRow(int rowIndex)
        {
            if (_rowCells.ContainsKey(rowIndex))
            {
                return _rowCells[rowIndex];
            }
            return null;
        }
        /// <summary>
        /// 获取整列单元格集合。
        /// </summary>
        /// <param name="columnName">列名。</param>
        /// <returns>返回单元格集合。</returns>
        public List<Cell> GetColumn(string columnName)
        {
            if (_columnCells.ContainsKey(columnName))
            {
                return _columnCells[columnName];
            }
            return null;
        }
        #endregion

        #region " 友元方法 "
        /// <summary>
        /// 当插入单元格时发生。
        /// </summary>
        /// <param name="index">要插入的索引。</param>
        /// <param name="value">单元格。</param>
        protected override void OnInsert(int index, object value)
        {
            Cell cell = (Cell)value;
            if (_canvas != null)
            {
                cell.Canvas = _canvas;
            }

            AddToRow(cell);
            AddToColumn(cell);

            cell.RowIndexChanged += new RowIndexChangedEventHander(cell_RowIndexChanged);
            cell.ColumnNameChanged += new ColumnNameChangedEventHandler(cell_ColumnNameChanged);

            base.OnInsert(index, value);

            OnChanged(new CollectionChangeEventArgs(CollectionChangeAction.Add, value));
        }
        /// <summary>
        /// 当移除单元格时发生。
        /// </summary>
        /// <param name="index">要移除的索引。</param>
        /// <param name="value">单元格。</param>
        protected override void OnRemove(int index, object value)
        {
            Cell cell = (Cell)value;
            if (_canvas != null)
            {
                cell.Canvas = null;
            }

            RemoveFromRow(cell, cell.RowIndex);
            RemoveFromColumn(cell, cell.ColumnName);

            cell.RowIndexChanged -= new RowIndexChangedEventHander(cell_RowIndexChanged);
            cell.ColumnNameChanged -= new ColumnNameChangedEventHandler(cell_ColumnNameChanged);

            base.OnRemove(index, value);

            OnChanged(new CollectionChangeEventArgs(CollectionChangeAction.Remove, value));
        }
        /// <summary>
        /// 当验证单元格是发生。
        /// </summary>
        /// <param name="value">单元格。</param>
        protected override void OnValidate(object value)
        {
            if (value.GetType() != typeof(Cell))
                throw new ArgumentException("value must be of type 'Cell'.", "value");
            base.OnValidate(value);
        }
        /// <summary>
        /// 当集合改变后发生。
        /// </summary>
        /// <param name="e">集合改变参数。</param>
        protected virtual void OnChanged(CollectionChangeEventArgs e)
        {
            if (Changed != null) Changed(this, e);
        }
        #endregion

        #region " 事件处理--Cell "
        /// <summary>
        /// 当单元格行号改变后发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void cell_RowIndexChanged(object sender, RowIndexChangedEventArgs e)
        {
            Cell cell = (Cell)sender;
            RemoveFromRow(cell, e.RowIndex);
            AddToRow(cell);
        }
        /// <summary>
        /// 当单元格列名改变后发生。
        /// </summary>
        /// <param name="sender">事件对象。</param>
        /// <param name="e">事件参数。</param>
        private void cell_ColumnNameChanged(object sender, ColumnNameChangedEventArgs e)
        {
            Cell cell = (Cell)sender;
            RemoveFromColumn(cell, e.ColumnName);
            AddToColumn(cell);
        }
        #endregion

        #region " 私有方法 "
        /// <summary>
        /// 将单元格添加到行。
        /// </summary>
        /// <param name="cell">单元格。</param>
        private void AddToRow(Cell cell)
        {
            if (!_rowCells.ContainsKey(cell.RowIndex))
            {
                _rowCells.Add(cell.RowIndex, new List<Cell>());
            }
            _rowCells[cell.RowIndex].Add(cell);
        }
        /// <summary>
        /// 将单元格添加到列。
        /// </summary>
        /// <param name="cell">单元格。</param>
        private void AddToColumn(Cell cell)
        {
            if (!_columnCells.ContainsKey(cell.ColumnName))
            {
                _columnCells.Add(cell.ColumnName, new List<Cell>());
            }
            _columnCells[cell.ColumnName].Add(cell);
        }
        /// <summary>
        /// 将单元格从行中移除。
        /// </summary>
        /// <param name="cell">单元格。</param>
        /// <param name="rowIndex">行号。</param>
        private void RemoveFromRow(Cell cell, int rowIndex)
        {
            if (_rowCells.ContainsKey(rowIndex))
            {
                _rowCells[rowIndex].Remove(cell);
                if (_rowCells[rowIndex].Count == 0) _rowCells.Remove(rowIndex);
            }
        }
        /// <summary>
        /// 将单元格从列中移除。
        /// </summary>
        /// <param name="cell">单元格。</param>
        /// <param name="columnName">列名。</param>
        private void RemoveFromColumn(Cell cell, string columnName)
        {
            if (_columnCells.ContainsKey(columnName))
            {
                _columnCells[columnName].Remove(cell);
                if (_columnCells[columnName].Count == 0) _columnCells.Remove(columnName);
            }
        }
        /// <summary>
        /// 获取单元格。
        /// </summary>
        /// <param name="rowIndex">行号。</param>
        /// <param name="columnName">列名。</param>
        /// <returns>成功，返回单元格，否则，返回 null。</returns>
        private Cell GetCell(int rowIndex, string columnName)
        {
            List<Cell> cells = GetRow(rowIndex);
            for (int i = 0; i < cells.Count; i++)
            {
                if (string.Compare(columnName, cells[i].ColumnName) == 0)
                {
                    return cells[i];
                }
            }
            return null;
        }
        #endregion
    }
}
